package com.yy.tech.inte.service.wrapper;

import com.yy.tech.inte.context.Content;
import com.yy.tech.inte.service.AbstractInteService;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * HttpRequest 包装类，设置好请求相关的参数，在{@link AbstractInteService(HttpRequestWrapper)}
 * 时构建成HttpRequest，并通过RestTemplate发出请求。
 *
 * @author YY
 * @version 1.0.0
 * @date $ $
 * @description: TODO
 */
public class HttpRequestWrapper <T,S>{
    private String uri;//api  url,if url is properties key,will get value ,and if not find from env,will use this value.

    private HttpMethod method= HttpMethod.POST;
    private HttpHeaders headers;
    private HttpHeaders tempHeaders;

    private Map<String,Object> uriVariables= new LinkedHashMap<>(8);//url  path variable
    private String targetType;//api host type
    private String authType = Content.DEFAULT_AUTH_TYPE;//request authorization type
    private S request;  //HttpRequest object
    private Class<T> responseClass;// response type
    private String hostType;
    private boolean logging = Boolean.TRUE;//write log or not
    private HttpEntity<S> httpEntity;
    private String requestUrl;//如果设置该值，则不会去根据uri构建url
    private String authToken;//指定认证Token


    public String getUri() {
        return uri;
    }

    public HttpRequestWrapper setUri(final String uri) {
        this.uri = uri;
        return this;
    }

    public HttpMethod getMethod() {
        return method;
    }

    public HttpRequestWrapper setMethod(final HttpMethod method) {
        this.method = method;
        return this;
    }

    public HttpHeaders getHeaders() {
        if(null == headers){
            headers = new HttpHeaders();
        }
        if (null != tempHeaders){
            headers.addAll(tempHeaders);
        }
        return headers;
    }

    public HttpRequestWrapper addHeader(String key,String value){
        if (null == tempHeaders){
            tempHeaders = new HttpHeaders();
        }
        tempHeaders.set(key,value);
        return this;
    }

    public HttpRequestWrapper setHeaders(final HttpHeaders headers) {
        this.headers = headers;
        return this;
    }

    public Map<String, Object> getUriVariables() {
        return uriVariables;
    }

    public HttpRequestWrapper addUriVariable(String name,Object value){
        uriVariables.put(name,value);
        return this;
    }

    public HttpRequestWrapper setUriVariables(final Map<String, Object> uriVariables) {
        this.uriVariables = uriVariables;
        return this;
    }

    public String getTargetType() {
        return targetType;
    }

    public HttpRequestWrapper setTargetType(final String targetType) {
        this.targetType = targetType;
        return this;
    }

    public String getAuthType() {
        return authType;
    }

    public HttpRequestWrapper setAuthType(final String authType) {
        this.authType = authType;
        return this;
    }

    public S getRequest() {
        return request;
    }

    public HttpRequestWrapper setRequest(final S request) {
        this.request = request;
        return this;
    }

    public Class<T> getResponseClass() {
        return responseClass;
    }

    public HttpRequestWrapper setResponseClass(final Class<T> responseClass) {
        this.responseClass = responseClass;
        return this;
    }

    public String getHostType() {
        return hostType;
    }

    public HttpRequestWrapper setHostType(final String hostType) {
        this.hostType = hostType;
        return this;
    }

    public boolean isLogging() {
        return logging;
    }

    public HttpRequestWrapper setLogging(final boolean logging) {
        this.logging = logging;
        return this;
    }

    public HttpEntity<S> getHttpEntity() {
        if (null == httpEntity){
            if (null != request){
                httpEntity=new HttpEntity<>(request,getHeaders());
            }else {
                httpEntity = new HttpEntity<>(getHeaders());
            }
        }
        return httpEntity;
    }

    public void setHttpEntity(final HttpEntity<S> httpEntity) {
        this.httpEntity = httpEntity;
    }

    public String getRequestUrl() {
        return requestUrl;
    }

    public void setRequestUrl(final String requestUrl) {
        setRequestUrl(requestUrl,false);
    }

    public void setRequestUrl(final String requestUrl,boolean force) {
        if (StringUtils.isEmpty(this.requestUrl) ||force){
            this.requestUrl = requestUrl;
        }
    }

    public HttpRequestWrapper setAuthToken(final String authToken) {
        this.authToken = authToken;
        return this;
    }

    public String getAuthToken() {
        return authToken;
    }

    public static <T,S> HttpRequestWrapper<T,S> create(String uri, String targetType){
        return create(uri,targetType,null,null,HttpMethod.GET);
    }

    public static <T,S> HttpRequestWrapper<T,S> createPut(String uri,String targetType,S request,Class<T> responseClass){
        return create(uri,targetType,request,responseClass,HttpMethod.PUT);
    }

    public static <T,S> HttpRequestWrapper<T,S> createPost(String uri,String targetType,S request,Class<T> responseClass){
        return create(uri,targetType,request,responseClass,HttpMethod.POST);
    }

    public static <T,S> HttpRequestWrapper<T,S> createGet(String uri,String targetType,S request,Class<T> responseClass){
        return create(uri,targetType,request,responseClass,HttpMethod.GET);
    }

    public static<T,S> HttpRequestWrapper<T,S> create(String uri,String targetType,S request,Class<T> responseClass,HttpMethod method){
        Assert.notNull(uri,"uri is not null.");
        Assert.notNull(targetType,"targetType is not null.");
        HttpRequestWrapper wrapper = new HttpRequestWrapper();
        wrapper.uri = uri;
        wrapper.targetType = targetType;
        wrapper.method = method;
        wrapper.request = request;
        wrapper.responseClass = responseClass;
        return wrapper;
    }
}
